<template>
  <div class="chart" :style="commpStyle">
    <!-- 画布顶部按钮 -->
    <div class="top-bar">
      <div @click="alarmButtnClick" class="alarmButtn">告警事件</div>
      <!-- 按钮区域 -->
      <div class="left-bar">
        <div class="leftBarImage">
          <div @click="zoom('big')" class="bigger"></div>
          <div @click="zoom('small')" class="smaller"></div>
          <div @click="center" class="focus"></div>
          <div @click="toggleFullScreen" class="maximize"></div>
        </div>
      </div>
    </div>
    <!-- 右键菜单区域 -->
    <div class="context-menu-container" :style="contextStyleObject">
      <layoutContainer :layout="layout" v-model="layoutValue" :theme="theme"></layoutContainer>
    </div>
    <!-- 报表图层区域 -->
    <div class="reportLayerContainer">
      <div class="reportItem" v-for="(report, index) in reportRender" :key="'report_'+index" :style="reportRenderStyleLocal[index]">
        <layoutContainer :layout="reportRenderLayoutLocal[index]" :theme="theme"></layoutContainer>
      </div>
    </div>
    <!-- 绘图容器区域 -->
    <canvas id="chart-root" class="chart-root"></canvas>
  </div>
</template>

<script>
import {
  getGraphicContent,
} from "../../assets/topo/chart.js";
import layoutContainer from "./layoutContainer.vue";
import commonMiniDialog from "./commonMiniDialog.vue";
import baseComp from "./baseComp";
import {AppManager} from "../../assets/topo/AppManager.js";
const _ = require("lodash");
export default {
  name: "topoFlowComps",
  extends: baseComp,
  components: {layoutContainer, commonMiniDialog},
  props: {
    topId: '', //当前画布需要绘制的指定数据ID
    layout: {
      type: Object,
      default: () => {
          return{
              row: 0,
              col: 0,
              render: [
                  // {rowNum: 1,colNum: 1,component: '',width: '',height: '', minWidth: '', minHeight: "", config: {}}
              ]
          }
      }
    },
    reportRender: []
  },
  data() {
    return {
      newflowInfoData: [],
      tempNode: null,
      fullScreenMode: false,
      contextStyleObject: {
        left: 0,
        top: 0,
        display: "none"
      },
      deleteLinkBtnStyleObject: false,
      // 选中的连线，用于删除
      selectedLink: null,
      currentConfigNode: {},
      currentTopId: this.topId,
      //布局组件数据内容
      layoutValue: {},
      //报表渲染本地数据，监听传递进来的数据内容
      reportRenderStyleLocal: [],
      reportRenderLayoutLocal: []
    };
  },
  watch: {
    topId: {
      handler(id, o) {
        this.currentTopId = id;
      },
      deep: true,
      immediate: true
    },
    reportRender: {
      handler(val, o) {
        for(var index = 0; index < val.length; index++){
          this.reportRenderStyleLocal[index] = this.getReportStyle(val[index]);
          this.reportRenderLayoutLocal[index] = this.getReportLayout(val[index]);
        }
      },
      deep: true,
      immediate: true
    }
  },
  created() {

  },
  mounted() {
    this.loadTheme(this.$options.name);
    this.postMessage(1);
    //修改自身父类el-form-item的底边距
    let currentEl = this.$el;
    let elItem = jQuery(currentEl).closest('.el-form-item');
    elItem.css('margin-bottom', '0px');
    window.setTimeout(()=>{
      this.handleResize();
      window.addEventListener('resize', this.handleResize);
    }, 100)
  },
  beforeDestroy(){
    window.removeEventListener('resize', this.handleResize);
  },
  destroyed() {
    this.postMessage(2);
    //界面关闭时，取消订阅。
    // this.closeSubscribe();
  },
  methods: {
    /**
     * 监听界面大小变化操作
     */
    handleResize(){
      //初始化画布容器
      this.initChartContainer();
      //初始化获取图形数据
      this.refreshChart();
    },
    /**
     *
     * @param type 发送全屏消息内容
     */
    postMessage(type){
        if(type==1){
            window.parent.postMessage(JSON.stringify({method:'openDialog'}),
            "*")
        }else if(type==2){
              window.parent.postMessage(JSON.stringify({method:'closeDialog'}),
            "*")
        }
    },
    /**
     * 订阅模块，实现业务数据订阅监听
     */
    subscribeRouter() {
      // 获取连接通道
      let ws = $websocket.getWs('topoDiscovery');
      let model = {
        'topoReport': (res) => {
          try {
            AppManager.instance.changeNodeStatus(res);
          } catch (error) {
            console.error('changeStatus failed', error)
          }
        }
      }
      ws.subscribeToModel('topoDiscovery', model, {});
    },

    /**
     * 关闭订阅
     */
    closeSubscribe() {
      // 获取连接通道
      let ws = $websocket.getWs('topoDiscovery');
      ws.unSubscribe('topoDiscovery')
    },

    /**
     * 告警按钮事件
     */
    alarmButtnClick(){
      //向外传递事件
      this.executeEvent('alarmButtnClick', this.path)
    },

    /**
     * 画图面板全屏切换
     */
    toggleFullScreen() {
    //   let app = AppManager.instance;
    //   this.fullScreenMode = !this.fullScreenMode;
    //   if (this.fullScreenMode) {
    //     // TODO 给我一个新的 w/h 就可以
    //     const {width, height} = document
    //       .getElementById("design-home")
    //       .getBoundingClientRect();
    //     // this.rootStyleObject = {
    //     //   width: width + "px",
    //     //   height: height + "px",
    //     //   left: "12px",
    //     //   top: "12px",
    //     //   "z-index": 10,
    //     //   position: "absolute"
    //     // };
    //     app.resize(width, height);
    //   } else {
    //     // this.rootStyleObject = {
    //     //   width: this.width + "px",
    //     //   height: "100%"
    //     // };
    //     // app.resize(this.width, this.height);
    //   }
    },

        /**
     *
     * @param {报表组件内容} report
     */
     getReportStyle(report){
      let style = {};
      if(report.top){
        style.top = report.top;
      }
      if(report.right){
        style.right = report.right;
      }
      if(report.bottom){
        style.bottom = report.bottom;
      }
      if(report.left){
        style.left = report.left;
      }
      if (report.width) {
        style.width = report.width;
      }
      if(report.height){
        style.height = report.height;
      }
      return style;
    },

    /**
     *
     * @param {报表组件内容} report
     */
    getReportLayout(report){
      return {
        row: 1,
        col: 1,
        render: [
          {rowNum: 1,colNum: 1,component: report.component, config: report.config}
        ]
      }
    },

    /**
     * 初始化图形数据接口
     */
    initOriginFlowData() {
      if (this.currentTopId) {
        getGraphicContent(this.currentTopId).then(graphicData => {
          if (graphicData) {
            let nodeDataList = graphicData.data.graph.nodes;
            let flowInfoData = graphicData.data.graph.topoPedag;
            this.newflowInfoData = flowInfoData;
            let viewNodeDatas = nodeDataList.map(nodeItem => {
              let tempItem = _.cloneDeep(nodeItem);
              tempItem.arcNodeId = nodeItem.nodeId;
              // 显示标识的地方
              //debugger
              tempItem.arcNodeName = nodeItem.name;
              // tempItem.arcNodeName = nodeItem.nodeName+'\n';
              // if(nodeItem.nodeIp){
              //   tempItem.arcNodeName += 'ip: '+nodeItem.nodeIp+'\n'
              // }
              // if(nodeItem.nodeMac){
              //   tempItem.arcNodeName += 'mac: '+nodeItem.nodeMac
              // }
              return tempItem;
            });
            let viewLinkDatas = flowInfoData.map(linkItem => {
              let tempItem = _.cloneDeep(linkItem);
              tempItem.fromArcNodeId = linkItem.fromPort;
              tempItem.toArcNodeId = linkItem.toPort;
              tempItem.fromNodeId = linkItem.fromId;
              tempItem.toNodeId = linkItem.toId;
              return tempItem;
            });
            AppManager.instance.showOriginData(
              viewNodeDatas,
              viewLinkDatas
            );
          }
        })
        .catch(error => {
          reject(error);
        });
      }
    },

    /**
     * 刷新画布面板
     */
    refreshChart() {
      AppManager.instance.clearCanvas();
      AppManager.instance.clearData();
      this.initOriginFlowData();
    },

    /**
     * 初始化容器
     */
    initChartContainer() {
      let chart = document.getElementsByClassName("chart")[0];
      let width = chart.clientWidth;
      let height = chart.clientHeight;
      let canvas = document.getElementById("chart-root");
      let chartApp = new AppManager(canvas, width, height);
      window.chartApp = chartApp;
      let vm = this
      chartApp.on("contextmenu", ({event, data}) => {
        this.contextStyleObject = {
          display: "flex",
          position: "absolute"
        };
        this.$nextTick(() => {
            //判断当前坐标与右键菜单高度，如果超出画布范围则向反方向弹出
            let contextMenuContainer = document.getElementsByClassName("context-menu-container")[0];
            let rect = contextMenuContainer.getBoundingClientRect();
            let contextMenuWidth = rect.width;
            let contextMenuHeight = rect.height;
            let x = event.offsetX;
            let y = event.offsetY;
            if((height - y) < contextMenuHeight){
              y = y - contextMenuHeight;
            }
            if((width - x) < contextMenuWidth){
              x = x - contextMenuWidth;
            }
            this.contextStyleObject = {
              left: `${x}px`,
              top: `${y}px`,
              // display: "flex",
              position: "absolute"
            };
        });

        this.currentConfigNode = data;
        //向外传递事件
        this.executeEvent('contextmenu', this.path, data);
      });

      //绑定清空选择事件
      chartApp.on("clearSelect", () => {
        this.contextStyleObject = {
          display: "none"
        };
        this.currentConfigNode = null;
      });

      //绑定添加节点之前的事件，判断当前节点类型是否为2：虚拟拓扑节点，如果不是则按正常流程流程，如果是则直接添加节点库。
      chartApp.on("beforeAddNode", async data => {
        this.tempNode = data;
      });

      //绑定删除节点事件
      chartApp.on("deleteNode", async node => {
        // TODO，删除节点
        // let param = {
        //   arcNodeId: node.b_data.arcNodeId
        // };
        // await deleteNode(param);
        // setTimeout(() => {
        //   this.refreshChart();
        // }, 32);
      });

      //绑定删除节点连线事件
      chartApp.on("deleteNodeLink", async link => {
        // await deleteNodeLink([link.id]);
        // setTimeout(() => {
        //   this.refreshChart();
        // }, 32);
      });


      //绑定点击节点事件
      chartApp.on("clickNode", node => {
        console.log("click node here...", node);
        this.$emit("clickNode", node);
      });

      //绑定节点移动事件
      chartApp.on('moveNode', node => {
        console.log('move node end...', node)
        const param = {
          id: node.b_data.id || node.b_data.nodeId,
          position: {x: node.x, y: node.y}
        }
        // updateNodePosition(param)
      })
    },

    /**
     * 实时修改节点状态
     * @param nodeData 节点数据
     */
    changeNodeStatus(nodeData){
      AppManager.instance.changeNodeStatus(nodeData)
    },

    /**
     * 改变连线颜色
     * @param linkData 连线数据
     */
    changeLinkStatus(linkData){
      AppManager.instance.changeLinkStatus(linkData)
    },

    center(){},

    /**
     * 控制缩放
     */
    zoom(type) {
      AppManager.instance.canvasZoom(type);
    },

    /**
     * 删除和目标节点关联的所有连线
     * @param toNodeId 目标节点ID 
     */
    deleteLink(toNodeId) {
      this.deleteLinkBtnStyleObject = false;
      AppManager.instance.deleteLink0(toNodeId);
    },

    /**
     * 动态添加线条
     * @param link 需要添加线条的数据内容
     */
    addLink(link){
      AppManager.instance.addLink0(link);
    },


    /**
     * 删除节点
     */
    deleteNode(resId) {
      this.contextStyleObject.display = "none";
      AppManager.instance.deleteNode0(resId);
    },


    /**
     * 动态添加节点
     * @param node 添加节点数据内容
     */
    addNode(node){
      AppManager.instance.addNode0(node);
      // AppManager.instance.addNode1(node);
    },

    /**
     * 初始化resize信息
     */
    // initResizeInfo() {
    //   const hEle = document.getElementById("h_resize_container");
    //   this.resizeOffsetInfo = this.getEleOffset(hEle);
    //   this.leftHeight = hEle.offsetHeight;
    //   this.containerWidth = document.getElementById(
    //     "v_resize_container"
    //   ).offsetWidth;
    // },

    /**
     * 获取元素的偏移信息
     */
    // getEleOffset(ele) {
    //   var clientTop = ele.offsetTop;
    //   var clientLeft = ele.offsetLeft;
    //   let current = ele.offsetParent;
    //   while (current !== null) {
    //     clientTop += current.offsetTop;
    //     clientLeft += current.offsetLeft;
    //     current = current.offsetParent;
    //   }
    //   return {
    //     clientTop,
    //     clientLeft,
    //     height: ele.offsetHeight,
    //     width: ele.offsetWidth
    //   };
    // },
    /**
     * 开始拖动水平调整块
     */
    // hResizeDown() {
    //   this.isHResize = true;
    // },

    /**
     * 拖动水平调整块
     */
    // hResizeOver(e) {
    //   const {isHResize, hNum, hNumLimit} = this.state;
    //   if (
    //     isHResize &&
    //     hNum >= hNumLimit &&
    //     this.resizeOffsetInfo.height - hNum >= hNumLimit
    //   ) {
    //     let newValue =
    //       this.resizeOffsetInfo.clientTop +
    //       this.resizeOffsetInfo.height -
    //       e.clientY;
    //     if (newValue < hNumLimit) {
    //       newValue = hNumLimit;
    //     }
    //     if (newValue > this.resizeOffsetInfo.height - hNumLimit) {
    //       newValue = this.resizeOffsetInfo.height - hNumLimit;
    //     }
    //     this.$set(this.state, "hNum", newValue);
    //   }
    // },

    /**
     * 开始拖动垂直调整块
     */
    // vResizeDown() {
    //   this.isVResize = true;
    // },

    /**
     * 拖动垂直调整块
     */
    // vResizeOver(e) {
    //   const {isVResize, vNum, vNumLimit} = this;
    //   if (isVResize) {
    //     let newValue = e.clientX - this.resizeOffsetInfo.clientLeft;
    //     if (newValue < vNumLimit) {
    //       newValue = vNumLimit;
    //     }
    //     if (newValue > this.containerWidth - vNumLimit) {
    //       newValue = this.containerWidth - vNumLimit;
    //     }
    //     this.$set(this.state, "vNum", newValue);
    //   }
    // },

    /**
     * 只要鼠标松开或者离开区域，那么就停止resize
     */
    // stopResize() {
    //   this.isVResize = false;
    //   this.isHResize = false;
    // },

  }
};
</script>

<style lang="less" scoped>

</style>

